﻿$(function () {
    app.body = $("#Main>#Content") || app.body;

    LayoutMain();
    $(window).resize(function () {
        LayoutMain();
    });
});
function LayoutMain() {
    var Left = $("#Main>#Left");

    var Page = $("#Main>#Left>#Page");

    var SystemLogo = $("#Main>#Left>#SystemLogo");
    var SystemName = $("#Main>#Left>#SystemName");
    var SystemInfo = $("#Main>#Left>#SystemInfo");

    Page.height(Left.height() - SystemLogo.height() - SystemName.height() - SystemInfo.height() - 30);

    $(".frame").each(function () {
        var me = $(this);

        if (me.hasClass("maximized")) {
            me.triggerHandler("resize");
        }
    });
}

var ESONFormat = {
    contentType: "Eson",
    encode: function (source) {
        var stringValue = this.getString(source);

        if (stringValue != null) {
            return stringValue;
        }

        if (source instanceof Array) {
            return this.encodeArray(source);
        }

        return this.encodeObject(source);
    },
    encodeArray: function (array) {
        var result = "{A|" + array.length;

        for (var i = 0; i < array.length; i++) {
            result += "|";
            result += this.encode(array[i]);
        }

        result += "}";

        return result;
    },
    encodeObject: function (object) {
        var fieldsCount = 0;
        var fieldsText = "";
        var valuesText = "";

        for (var name in object) {
            ++fieldsCount;

            fieldsText += "|";
            fieldsText += name;

            valuesText += "|";
            valuesText += this.encode(object[name]);
        }

        return "{O|" + fieldsCount + fieldsText + valuesText + "}";
    },
    getString: function (value) {
        if (value == null) {
            return "null";
        }

        if (typeof value == "string") {
            if (value.length == 0) {
                return "";
            }

            switch (value) {
                case "null":
                    return "Snull";
                case "true":
                    return "Strue";
                case "false":
                    return "Sfalse";
            }

            if (/^[0-9]+(\.[0-9]+)?$/.test(value)) {
                return "S" + value;
            }

            value = this.escape(value);

            switch (value[0]) {
                case 'S':
                case 'D':
                    return "S" + value;
            }

            return value;
        }

        if (value instanceof Date) {
            return "D" + (value.getTime());
        }

        if (typeof value == "number") {
            return String(value);
        }

        if (typeof value == "boolean") {
            return String(value);
        }

        return null;
    },
    escape: function (text) {
        if (typeof text == "string") {
            var length = text.length;

            for (var i = 0; i < text.length; i++) {
                switch (text[i]) {
                    case '~':
                    case '|':
                    case '{':
                    case '}':
                        ++length;
                        break;
                }
            }

            if (length == text.length) {
                return text;
            }

            var result = "";

            for (var i = 0; i < text.length; i++) {
                switch (text[i]) {
                    case '~':
                        result += "~";
                        result += "1";
                        break;
                    case '|':
                        result += "~";
                        result += "2";
                        break;
                    case '{':
                        result += "~";
                        result += "3";
                        break;
                    case '}':
                        result += "~";
                        result += "4";
                        break;
                    default:
                        result += text[i];
                }
            }

            return result;
        } else {
            throw "ESONFormat.escape : text 必须的 string 类型";
        }
    },
    internalDecode: function (text, begin, end, fields, values) {
        if (typeof text == "string" && typeof begin == "number" && typeof end == "number" && fields instanceof Array && values instanceof Array) {
            var type = null;

            var index = 0;
            var fieldsCount = 0;

            while (true) {
                switch (text[begin]) {
                    case '{':
                        ++begin;

                        switch (text[begin]) {
                            case 'T':
                            case 'O':
                            case 'A':
                                type = text[begin];
                                break;
                            default:
                                throw "ESONFormat.decode : 无效的 eson 格式";
                        }

                        begin += 2;

                        index = text.indexOf("|", begin, end);
                        index = index == -1 ? end : Math.min(index, end);

                        fieldsCount = parseInt(text.substring(begin, index));

                        begin = index;

                        break;
                    case '}':
                        return type;
                    case '|':
                        ++begin;

                        if (type != "A" && fields.length < fieldsCount) {
                            index = text.indexOf("|", begin, end);
                            index = index == -1 ? end : Math.min(index, end);

                            fields.push(text.substring(begin, index));
                        } else {
                            var value;

                            if (text[begin] == '{') {
                                index = text.relativeIndexOf("{", "}", begin + 1, end);

                                value = this.decode(text, begin, index);

                                ++index;
                            } else {
                                index = text.indexOf("|", begin, end);
                                index = index == -1 ? end : Math.min(index, end);

                                value = this.parseValue(this.unEscape(text.substring(begin, index)));
                            }

                            values.push(value);
                        }

                        begin = index;

                        break;
                    default:
                        throw "ESONFormat.decode : 无效的 eson 格式";
                }
            }
        } else {
            throw "ESONFormat.internalDecode : 参数格式错误"
        }
    },
    unEscape: function (text) {
        if (typeof text == "string") {
            var length = text.length;
            var right = length - 1;

            for (var i = 0; i < right; i++) {
                if (text[i] == '~') {
                    --length;
                }
            }

            if (length == text.length) {
                return text;
            }

            var result = "";

            var i = 0;
            for (; i < right; ++i) {
                if (text[i] == '~') {

                    ++i;

                    switch (text[i]) {
                        case '1':
                            result += "~";
                            break;
                        case '2':
                            result += "|";
                            break;
                        case '3':
                            result += "{";
                            break;
                        case '4':
                            result += "}";
                            break;
                    }
                } else {
                    result += text[i];
                }
            }

            if (i == right) {
                result += text[i];
            }

            return result;
        } else {
            throw "ESONFormat.unEscape : 参数格式错误";
        }
    },
    parseValue: function (text) {
        if (typeof text == "string") {
            switch (text) {
                case "null":
                    return null;
                case "true":
                    return true;
                case "false":
                    return false;
            }

            if (text.length == 0) {
                return "";
            }

            switch (text[0]) {
                case 'S':
                    return text.substr(1);
                case 'D':
                    return new Date(parseInt(text.substr(1)))
            }

            if (/^[0-9]+(\.[0-9]+)?$/.test(text)) {
                return parseFloat(text);
            }

            return text;
        } else {
            throw "ESONFormat.parseValue : 参数格式错误";
        }
    },
    decode: function (text, begin, end) {
        if (begin === undefined && end === undefined) {
            begin = 0;
            end = text.length - 1;
        }

        if (typeof text == "string" && typeof begin == "number" && typeof end == "number") {

            var fields = [];
            var values = [];

            var type = this.internalDecode(text, begin, end, fields, values);

            if (type == "A") {
                return values;
            }

            var result = [];

            for (var i = 0; i < values.length; i++) {
                var name = fields[i % fields.length];
                var value = values[i];
                var index = parseInt(i / fields.length);
                if (index == result.length) {
                    result.push({});
                }
                result[index][name] = value;
            }

            if (type == "O") {
                return result[0];
            }

            return result;

        } else {
            throw "ESONFormat.decode : 参数格式错误";
        }
    }
}
var JSONFormat = {
    contentType: "Json",
    encode: function (source) {
        source = this.asValues(source);
        return JSON.stringify(source);
    },
    decode: function (text) {
        return eval("(" + text + ")");
    },
    asValues: function (object) {
        if (object instanceof Date) {
            return object.getFullYear() + "-" + (object.getMonth() + 1) + "-" + object.getDate() + " " + object.getHours() + ":" + object.getMinutes() + ":" + object.getSeconds();
        } else if (object instanceof Array) {
            for (var i = 0; i < object.length; i++) {
                object[0] = this.asValues(object[0]);
            }
        } else if (typeof object == "object") {
            for (var name in object) {
                object[name] = this.asValues(object[name]);
            }
        }

        return object;
    },
    getString: function (object) {
        return this.encode(object);
    }
}

var app = {
    token: "8522ef7e4aa84fdc884fd4db6786924e",
    appid: "2770db0aa17c4e8f9e66751b976d4ebe",
    body: $(document.body),
    defaultFormat: JSONFormat,
    defaultPrimaryKey: "Id",
    defaultFailure: function () {

    },
    defaultSuccess: function () {

    },
    defaultDownload: function () {
    },
    IdentityKey: "Identity",
    url: "http://localhost:50968/api/",
    buffered: {},
    jquery: function (jquery) {
        if (typeof jquery == "string") {
            jquery = $(jquery);
        } else if (jquery instanceof HTMLElement) {
            jquery = $(jquery);
        }

        if (!jquery.jquery) {
            throw "必须是 JQurey 对象";
        }

        return jquery;
    },
    show: function (tempFrame) {
        tempFrame = app.jquery(tempFrame);

        var frame = tempFrame.clone(true);

        frame.prop("id", "");

        frame.removeClass("temp");

        function SetZIndex(Me) {
            var ZIndex = app._ZIndex = (app._ZIndex || 0) + 1;

            Me.css("z-index", ZIndex);
        }

        SetZIndex(frame);

        frame.mousedown(function () {
            SetZIndex($(this));
        });

        frame.find(".close").click(function () {
            frame.trigger("close");

            frame.remove();
        });

        frame.find(".max").click(function () {
            if (frame.hasClass("minimized")) {
                frame.removeClass("minimized");
            } else {
                frame.toggleClass("maximized");
            }

            frame.triggerHandler("resize");
        });

        frame.find(".min").click(function () {
            frame.addClass("minimized");
            frame.removeClass("maximized");

            frame.triggerHandler("resize");
        });

        frame.find(".top").mousedown(function (e) {
            if (frame.hasClass("maximized")) {
                return;
            }

            var target = $(e.target);

            if (target.hasClass("min")
                || target.hasClass("max")
                || target.hasClass("close")
                || target.hasClass("right")) {
                return;
            }

            var win = $(window);

            var removeGrip = $(document.createElement("div"));

            var oX = e.offsetX;
            var oY = e.offsetY;

            var wWidth = win.width();
            var wHeight = win.height();

            var fWidth = frame.width();
            var fHeight = frame.height();

            removeGrip.addClass("remove-grip");
            removeGrip.width(frame.width());
            removeGrip.height(frame.height());

            move(removeGrip, e.clientX - oX, e.clientY - oY);
            app.body.append(removeGrip);

            function move(ele, x, y) {
                x = Math.max(x, 0);
                x = Math.min(x, wWidth - fWidth);
                y = Math.max(y, 0);
                y = Math.min(y, wHeight - fHeight);

                ele.css("left", x + "PX");
                ele.css("top", y + "PX");
            }

            function mouseMove(e) {
                e.preventDefault();

                move(removeGrip, e.clientX - oX, e.clientY - oY);
            }
            function mouseUp(e) {
                e.preventDefault();
                removeGrip.remove();

                frame.css("margin-left", "0px");
                frame.css("margin-top", "0px");

                move(frame, e.clientX - oX, e.clientY - oY);

                win.unbind("mousemove", mouseMove);
                win.unbind("mouseup", mouseUp);
            }
            win.mousemove(mouseMove);
            win.mouseup(mouseUp);
        });

        app.body.append(frame);

        frame.resize(function () { app.contentLayout(frame); });

        app.contentLayout(frame);

        frame.trigger("show");

        return frame;
    },
    contentLayout: function (content) {
        content.find(".content .fit").each(function () {
            var me = $(this);
            var parent = me.parent();
            me.outerWidth(parent.width());
            me.outerHeight(parent.height() - 44);
        });
    },
    apply: function (form, data) {
        form = app.jquery(form);

        form.trigger("Apply", [data]);

        for (var name in data) {
            var element = form.find("[name='" + name + "']").not(form.find(".many[name = '" + name + "']"));

            if (element.length == 0) {
                continue;
            }

            var value = data[name];

            element.each(function (index) {
                if (this.tagName == "INPUT" && (this.type == "checkbox" || this.type == "radio")) {
                    this.checked = value instanceof Array ? value.findIndex(this.value) != -1 : value == this.value;
                } else {
                    var itemValue = value instanceof Array ? value[index] : value;

                    switch (this.tagName) {
                        case "INPUT":
                        case "SELECT":
                        case "TEXTAREA":
                            this.value = itemValue;
                            this._ControlValue = itemValue;

                            $(this).change();
                            break;
                        case "VIDEO":
                        case "IMG":
                            this.src = itemValue;
                    }
                }
            });
        }

        form.find("[display-where]").each(function () {
            var me = $(this);
            var result = eval(me.attr("display-where"));
            result ? me.removeClass("ignore") : me.addClass("ignore");
        });

        form.find("[readonly-where]").each(function () {
            var me = $(this);
            var result = eval(me.attr("readonly-where"));
            result ? me.attr("readonly", "readonly") : me.removeClass("readonly");
        });
    },
    now: function () {
        return new Date(Date.now());
    },
    server: function (data, success, failure, url, format) {
        url = url || app.url;
        failure = failure || app.defaultFailure;
        success = success || app.defaultSuccess;

        if (success == "Download") {
            success = app.defaultDownload;
        }

        if (typeof format == "string") {
            switch (format) {
                case "Json":
                    format = JSONFormat;
                    break;
                case "Eson":
                case "Default":
                    format = ESONFormat;
                    break;
            }
        }

        format = format || app.defaultFormat;

        if (typeof data == "object" && typeof success == "function" && typeof failure == "function" && typeof url == "string" && typeof format == "object") {

            if (typeof data.Command != "string") {
                throw "app.server : data.Command 无效";
            }

            $.extend(data, { Token: app.token, Time: app.now(), AppId: app.appid, ContentType: "Json" });

            if (app.userId && app.userName) {
                $.extend(data, { UserId: app.userId, UserName: app.userName });
            }

            var verify = "";

            for (var name in data) {
                verify += "&";
                verify += name;
                verify += "=";
                verify += data[name];
            }

            data.Verify = app.md5(verify.substr(1));

            if (success == app.defaultDownload) {
                var downloadFrame = app.buildElement({
                    tag: "iframe", id: "Download-IFrame", style: { display: "none" }, events: {
                        load: function () {
                            var items = [];
                            for (var name in data) {
                                var item = data[name];
                                if (item instanceof HTMLInputElement) {
                                    item.name = name;
                                    items.push(item);
                                } else {
                                    items.push({ tag: "input", name: name, value: item });
                                }
                            }

                            $(downloadFrame.contentWindow.document.body).append(app.buildElement({
                                tag: "form", method: "post", action: app.url, items: items
                            }));

                            downloadFrame.contentWindow.document.forms[0].submit();
                        }
                    }
                });
                app.body().append(downloadFrame);

                return "Download";
            }
            var uesFormData = false;

            for (var name in data) {
                if (data[name] instanceof HTMLInputElement) {
                    uesFormData = true;
                    break;
                }
            }

            if (uesFormData && window.FormData) {
                var formData = new FormData();

                for (var name in data) {
                    var value = data[name];
                    if (value instanceof HTMLInputElement) {
                        switch (value.type) {
                            case "file":
                                for (var i = 0; i < value.files.length; i++) {
                                    formData.append(name, value.files[i]);
                                }
                                break;
                            default:
                                formData.append(name, value.value);
                                break;
                        }
                    } else {
                        formData.append(name, value);
                    }
                }

                data = formData;
            }

            var uesBuffered = app.useBuffered(data.Command);
            var bufferedKey;

            if (uesBuffered) {
                bufferedKey = url;

                for (var name in data) {
                    switch (name) {
                        case "Time":
                        case "Reload":
                        case "Verify":
                            continue;
                    }

                    bufferedKey += "&";
                    bufferedKey += name;
                    bufferedKey += "=";
                    bufferedKey += data[name];
                }

                bufferedKey = app.md5(bufferedKey);

                if (!data.Reload && app.buffered[bufferedKey]) {
                    setTimeout(function () {
                        ProcessData(app.buffered[bufferedKey]);
                    });

                    return "Buffered";
                }
            }
            var httpRequest;

            if (window.XMLHttpRequest) {
                httpRequest = new XMLHttpRequest();
            }
            else {
                httpRequest = new ActiveXObject("Microsoft.XMLHTTP");
            }

            httpRequest.open("POST", url, true);

            httpRequest.setRequestHeader("Content-Type", format.contentType);

            function ProcessData(result) {
                if (result instanceof Array) {
                    success(result);
                    return;
                }

                if (typeof result == "string") {
                    success(result);
                    return;
                }

                switch (result.Code) {
                    case undefined:
                    case 0x0:
                        /* 成功 */
                        success(result);
                        break;
                    case 0x1:
                        /* 失败 */
                        app.msg(result.Msg);
                        failure(result);
                        break;
                    case 0x2:
                        /* 需要用户确认 */
                        app.confirm(result.Msg, function () {
                            alert("TODO : 处理新命令");
                        });
                        break;
                    case 0x4:
                        /* 成功并提示 */
                        app.msg(result.Msg);
                        success(result);
                        break;
                    case 0x8:
                        /* 跳转 Url */
                        alert(result.Msg);
                        location = result.Url;
                        break;
                    case 0x10:
                        /* 未授权 */
                        alert(result.Msg);
                        failure(result);
                        location = "/";
                        break;
                }
            }

            httpRequest.onreadystatechange = function () {
                if (this.readyState == 4) {
                    if (this.status == 200) {
                        var decodeFormat = data.ContentType;

                        switch (decodeFormat) {
                            case "Json":
                                decodeFormat = JSONFormat;
                                break;
                            case "Eson":
                            case "Default":
                            default:
                                decodeFormat = ESONFormat;
                                break;
                        }

                        decodeFormat = decodeFormat || app.defaultFormat;

                        var result = decodeFormat.decode(httpRequest.responseText);

                        if (uesBuffered) {
                            app.buffered[bufferedKey] = result;
                        }

                        ProcessData(result);
                    } else {
                        /* HTTP 错误 */
                        failure({ Code: this.status, Msg: httpRequest.responseText });
                    }
                }
            }

            httpRequest.send(format.encode(data));

            return "Ajax";
        } else {
            throw "app.server : 参数格式错误";
        }
    },
    useBuffered: function (commandName) {
        // 因为缓存很多时候严重影响用户体验，所以暂时禁用。
        return false;
        //if (typeof commandName == "string") {
        //    return (commandName.startsWith("Read") || commandName.startsWith("Get"));
        //} else {
        //    throw "app.useBuffered : 参数格式错误";
        //}
    },
    md5: function (text) {
        return md5(text);
    },
    msg: function (text) {
        alert(text);
    },
    errMsg: function (text) {
        alert(text);
    },
    confirm: function (text, callback) {
        if (confirm(text)) {
            callback();
        }
    },
    verifies: {
        /** 非空验证 */
        NotNull: function (Elemet, Name, Value) {
            if (Value === "" || Value === null || Value === undefined) {
                app.errMsg(Name + " 不能为空！")
                return false;
            }
            return true;
        },
        /** 数字验证 */
        Number: function (Elemet, Name, Value) {
            if (!/^[0-9]+(\.[0-9]+)?$/.test(Value) && Value) {
                app.errMsg(Name + " 只能填写数字!");
                return false;
            }
            return true;
        },
    },
    frameSubmit: function (Frame, Data, Callback) {
        Frame = $(Frame);

        var Command = Frame.attr("command");

        var Text = Frame.attr("text");

        Callback = Callback || function () {
            app.msg(Text + " 提交成功！");
        };

        if (!Command) {
            app.errMsg(Text + " Frame 提交失败，因为该 Frame 没有设置提交命令(Command)属性");
            return
        }

        var NullValue = {};

        var Elements = Frame.find("[name]:not(.many [name])");

        function GetValue(Element) {
            if (Element.tagName == "TEXTAREA") {
                return Element.value;
            }
            if (Element.tagName == "INPUT") {
                switch (Element.type.toUpperCase()) {
                    case "CHECKBOX":
                    case "RADIO":
                        if (Element.checked) {
                            return Element.value;
                        }
                        return NullValue;
                    default:
                        return Element.value;
                }
            }
            if (Element.tagName == "SELECT") {
                return Element.value;
            }

            return NullValue;
        }

        Data = Data || {};
        var Lengths = {};

        for (var i = 0; i < Elements.length; i++) {
            var Item = Elements[i];

            var Name = $(Item).attr("name");
            var Value = GetValue(Item);

            if (Value == NullValue) {
                continue;
            }

            var Verify = $(Item).attr("verify");

            if (Verify) {
                Verify = Verify.split(",");

                for (var j = 0; j < Verify.length; j++) {
                    var VerifyFunction = app.verifies[Verify[j]];

                    if (!VerifyFunction || typeof (VerifyFunction) != "function") {
                        app.errMsg("验证器 " + Verify[j] + " 未定义或无效");
                        return false;
                    }
                    if (!VerifyFunction(Item, Name, Value)) {
                        return false;
                    }
                }
            }

            Lengths[Name] = Lengths[Name] ? Lengths[Name] + 1 : 1;

            if (Lengths[Name] == 1) {
                Data[Name] = Value;
            } else if (Lengths[Name] == 2) {
                Data[Name] = [Data[Name], Value];
            } else {
                Data[Name].push(Value);
            }
        }

        Frame.triggerHandler("Process", [Data]);

        Data.Command = Command;

        app.server(Data, function (Result) {
            var PrimaryKey = Frame.attr("primary-key");

            var PrimaryValue = Data[PrimaryKey] || Result[app.IdentityKey] || Data[app.defaultPrimaryKey];

            var ManyItems = Frame.find(".many .item:not(.many .many .item)");

            if (ManyItems.length && !PrimaryValue) {
                app.errMsg(Text + " 的 Many Frame 提交失败，因为该 Frame 没有设置主键(Primary-Key)属性");

                return;
            }

            var Index = -1;

            function SubmitMany() {

                ++Index;

                if (Index == ManyItems.length) {
                    Callback(Result);
                    return;
                }

                var Item = $(ManyItems[Index]);

                var Many = Item.parents(".many:first");

                var Field = Many.attr("field");
                var Text = Many.attr("text");
                var Command = Many.attr("command");

                if (!Field) {
                    app.errMsg(Text + " Many Frame 提交失败，因为该 Many Frame 没有设置关联字段(Field)属性");

                    SubmitMany();

                    return;
                }

                var Data = {};

                Data[Field] = PrimaryValue;

                Many.removeClass("many");

                Item.attr("text", Text);
                Item.attr("command", Command);

                app.frameSubmit(Item, Data, function (Result) { SubmitMany(); });

                Item.removeAttr("text");
                Item.removeAttr("command");

                Many.addClass("many");
            }

            SubmitMany();
        });

        return false;
    },
    setParams: function (Resource, Data) {
        var Elements = $(".data-fill[resource=\"" + Resource + "\"]");

        function GetPropertyName(Element) {
            if (Element.tagName == "INPUT") {
                return "value";
            }

            return "innerHTML";
        }

        Elements.each(function () {
            var PropertyName = GetPropertyName(this);

            var Text = this._SetParams_Old_Text = (this._SetParams_Old_Text || this[PropertyName]);

            var NewText = app.format(Text, Data);

            if (NewText != Text) {
                this[PropertyName] = NewText;

                if ($(this).hasClass("only-first")) {
                    $(this).removeClass("only-first").removeClass("data-fill");
                }
            }
        });
    },
    format: function (Text, Data) {
        var Regex = /@([A-Za-z0-9_]+)/g;
        var Result = "";
        var Index = 0;
        var Match;
        var HasMatch = false;

        while ((Match = Regex.exec(Text))) {
            HasMatch = true;

            Result += Text.substring(Index, Match.index);
            Result += Data[Match[1]];

            Index = Match.index + Match[0].length;
        }

        if (HasMatch && Index != Text.length) {
            Result += Text.substring(Index);
        }

        return Result;
    },
    getDestElements: function (Resource) {
        var Resources = Resource.split(",");
        var Selecter = "";

        $(Resources).each(function () {
            Selecter += (",#" + this.trim());
        });

        return $(Selecter.substr(1));
    },
    controls: {
        table: function (Element) {
            var Me = $(Element);
            var Data = Element.Data;
            var IsTable = Element._IsTable || false;

            if (!Data) {
                Data = Me.attr("data");

                Data = eval("({" + Data + "})");

                Element.Data = Data;
            }

            if (!Data.Command) {
                Data.Command = Me.attr("command");
            }

            if (!Data.Command) {
                throw "无法初始化表格，因为没有指定读取数据的命令。";
            }

            var Columns = Me.find("thead tr td[name]");

            var Sorts = Me.find("thead tr td[name].sort");

            if (!IsTable) {
                /* 为排序列添加方向元素 */
                Sorts.append("<span class=\"sort-dir\"></span>");

                /* 设置排序列的点击事件 */
                Sorts.click(function () {
                    this._SortIndex = app._SortIndex = (app._SortIndex || 0) + 1;

                    var Direction = $(this).find(".sort-dir");

                    if (Direction.hasClass("asc")) {
                        Direction.removeClass("asc").addClass("desc");
                    } else if (Direction.hasClass("desc")) {
                        Direction.removeClass("desc");
                    } else {
                        Direction.addClass("asc");
                    }

                    app.controls.table(Element);
                });

                Me.find("thead tr td[name=selection] input[type=checkbox]").click(function () {
                    if (this.checked) {
                        Me.find("tbody tr td input[type=checkbox].selection:not(:checked)").click();
                    } else {
                        Me.find("tbody tr td input[type=checkbox].selection:checked").click();
                    }
                });

                Element.GetSelected = function () {
                    var SelectedRows = Me.find("tbody tr.selected");
                    var Result = [];

                    for (var i = 0; i < SelectedRows.length; i++) {
                        Result.push($.extend({}, SelectedRows[i].Data));
                    }

                    return Result;
                };
            }

            var Orders = "";

            Sorts.sort((Before, After) => {
                return (After._SortIndex || 0) - (Before._SortIndex || 0);
            });

            Sorts.each(function () {
                var Direction = $(this).find(".sort-dir");

                if (Direction.hasClass("asc")) {
                    Orders += ",A" + $(this).attr("name");
                } else if (Direction.hasClass("desc")) {
                    Orders += ",D" + $(this).attr("name");
                }
            });

            if (Orders) {
                Data.Orders = Orders.substr(1);
            } else {
                delete Data.Orders;
            }

            var InternalColumns = {
                selection: function (Data, Name, RowIndex, ColumnIndex) {
                    var Me = $(this);

                    var Result = document.createElement("input");

                    Result.type = "checkbox";

                    $(Result).addClass("selection");

                    $(Result).click(function () {
                        var Row = $(Me.find("tbody tr")[RowIndex]);

                        var Selection = Me.find("thead tr td[name=selection] input[type=checkbox]");

                        if (this.checked) {
                            Row.addClass("selected");

                            if (Me.find("tbody tr td input[type=checkbox].selection:checked").length == Me.find("tbody tr td input[type=checkbox].selection").length) {
                                Selection.prop("checked", true);
                            }
                        } else {
                            Row.removeClass("selected");

                            Selection.prop("checked", false);
                        }
                    });

                    Me.find("input[type=checkbox]").prop("checked", false);

                    return Result;
                }
            };

            app.server(Data, function (Result) {
                if (Result.length) {
                    var FirstRow = Result[0];

                    app.setParams(Element.id, { Count: Result.length });

                    Columns.each(function () {
                        var Me = $(this);
                        var Name = Me.attr("name");

                        if (FirstRow[Name] === undefined && InternalColumns[Name] === undefined) {
                            Me.addClass("temp");
                        } else {
                            Me.removeClass("temp");
                        }
                    });

                    Columns = Me.find("thead tr td[name]:not(.temp)");

                    var Body = $(document.createElement("tbody"));

                    for (var i = 0; i < Result.length; i++) {
                        var Tr = $(document.createElement("tr"));
                        var Data = Result[i];

                        Tr.prop("Data", Data);

                        for (var j = 0; j < Columns.length; j++) {
                            var Column = Columns[j];
                            var Name = $(Column).attr("name");
                            var Td = $(document.createElement("td"));
                            var Renderer = Column.Renderer;

                            if (!Renderer) {
                                Renderer = $(Column).attr("renderer");

                                if (Renderer) {
                                    Renderer = eval("(function(Data, Name, RowIndex, ColumnIndex){" + Renderer + "})");
                                } else if (InternalColumns[Name]) {
                                    Renderer = InternalColumns[Name];
                                } else {
                                    Renderer = function (Data, Name, RowIndex, ColumnIndex) {
                                        return Data[Name];
                                    };
                                }

                                Column.Renderer = Renderer;
                            }

                            var Value = Renderer.apply(Element, [Data, Name, i, j]);

                            if (Value instanceof HTMLElement) {
                                Td.append(Value);
                                Td.prop("title", Value.innerText);
                            } else {
                                Td.text(Value);
                                Td.prop("title", Value);
                            }

                            Tr.append(Td);
                        }

                        Body.append(Tr);
                    }

                    SetBody(Body);
                } else {
                    SetText("-V- 没有数据");
                }
            });

            function SetBody(Body) {
                Me.find("tbody").remove();
                Me.append(Body);
            }

            function SetText(Text) {
                SetBody("<tbody><tr><td colspan='" + Columns.length + "' style='height:100px;' >" + Text + "</td></tr></tbody>");
            }

            SetText("加载中...");

            Element._IsTable = true;
        },
        paging: function (Element) {
            var Me = $(Element);
            var Resource = $(Me).attr("resource");
            var DestElement = document.getElementById(Resource);
            var DestData = DestElement.Data;
            var Data = {};
            var IsPaging = Element._IsPaging || false;
            var Buttons = Element._Buttons || $();

            $.extend(Data, DestData);
            var Command = Me.attr("command");

            if (!Command) {
                throw "无法初始化分页工具，因为没有指定读取命令。";
            }

            Data.Command = Command;

            var Begin = Data.Begin;
            var End = Data.End;
            var PageSize = End - Begin + 1;

            delete Data.Begin;
            delete Data.End;

            function RefreshButtons(PageSize, Current, Total) {
                app.setParams(Element.id, { Total: Total, PageSize: PageSize, Current: Current });

                var MaxPage = Total % PageSize == 0 ? Total / PageSize : parseInt(Total / PageSize) + 1;
                var MidIndex = parseInt(Buttons.length / 2) + 1;
                var Index = Current < MidIndex ? 1 : Current + Buttons.length - MidIndex > MaxPage ? MaxPage - Buttons.length + 1 : Current - MidIndex + 1;

                Buttons.each(function () {
                    var Me = $(this);

                    this.value = Index;

                    if (Index > MaxPage || Index < 1) {
                        Me.addClass("temp");
                    } else {
                        Me.removeClass("temp");
                    }

                    if (Index == Current) {
                        Me.addClass("current");
                    } else {
                        Me.removeClass("current");
                    }

                    ++Index;
                });

                Me.find(".max-page").html("共 " + MaxPage + " 页");
            }

            app.server(Data, function (Result) {
                var Current = parseInt(End / PageSize);
                var Total = Element.Total = Result.Total;

                RefreshButtons(PageSize, Current, Total);
            });

            if (!IsPaging) {
                Me.find(".button[value]").each(function () {
                    if (!isNaN(parseInt(this.value))) {
                        Buttons.push(this);

                        this.value = parseInt(this.value);
                    }
                });

                Buttons.sort(function (Before, After) {
                    return Before.value - After.value;
                });

                Me.find(".button[value]").click(function () {
                    var Data = DestElement.Data;

                    var Begin = Data.Begin;
                    var End = Data.End;

                    var PageSize = End - Begin + 1;
                    var Current = parseInt(End / PageSize);

                    var Total = Element.Total;
                    var MaxPage = Total % PageSize == 0 ? Total / PageSize : parseInt(Total / PageSize) + 1;

                    var Value = this.value;

                    switch (Value) {
                        case "上一页":
                            Value = Current - 1;
                            break;
                        case "第一页":
                            Value = 1;
                            break;
                        case "下一页":
                            Value = Current + 1;
                            break;
                        case "最后一页": ;
                            Value = Total;
                            break;
                        case "GO":
                            var Input = $(this.parentElement).find("input[type=text]");
                            var Value = Input.val();
                            Input.val("");
                            break;
                    }

                    Value = parseInt(Value);

                    if (isNaN(Value)) {
                        Value = Current;
                    }

                    if (Value < 1) {
                        Value = 1;
                    }

                    if (Value > MaxPage) {
                        Value = MaxPage;
                    }

                    if (Value != Current) {
                        Data.Begin = (Value - 1) * PageSize + 1;
                        Data.End = Value * PageSize;

                        app.control($(DestElement));

                        RefreshButtons(PageSize, Value, Total);
                    }

                    return false;
                });

                Me.find(".first-size").html(PageSize).removeClass("first-size");

                Me.find(".filter select.input").change(function () {
                    var PageSize = parseInt(this.value);
                    var Total = Element.Total;

                    var Data = DestElement.Data;

                    Data.Begin = 1;
                    Data.End = PageSize;

                    app.control($(DestElement));

                    RefreshButtons(PageSize, 1, Total);
                });

                Element._Buttons = Buttons;
                IsPaging = Element._IsPaging = true;
            }
        },
        content: function (Element) {
            var Me = $(Element);

            Me.find(".tools .refresh").click(function () {
                var Resource = $(this).attr("Resource");

                app.getDestElements(Resource).each(function () {
                    if (this.Data) {
                        this.Data.Reload = true;
                    }

                    app.control($(this));

                    if (this.Data) {
                        delete this.Data.Reload;
                    }
                });
            });

            Me.find(".tools .insert").click(function () {
                var Resource = $(this).attr("Resource");
                var Command = $(this).attr("Command");
                var Frame = $(this).attr("Frame");

                Frame = $(document.getElementById(Frame));

                if (Command) {
                    Frame.attr("Command", Command);
                }

                app.getDestElements(Resource).each(function () {
                    app.show(Frame);
                });
            });

            Me.find(".tools .update").click(function () {
                var Resource = $(this).attr("Resource");
                var Command = $(this).attr("Command");
                var Frame = $(this).attr("Frame");

                Frame = $(document.getElementById(Frame));

                if (Command) {
                    Frame.attr("Command", Command);
                }

                app.getDestElements(Resource).each(function () {
                    var Selected = this.GetSelected();

                    if (Selected.length == 0) {
                        app.msg("请选择您要修改的数据！");
                        return;
                    }

                    for (var i = 0; i < Selected.length; i++) {
                        var Flag = app.show(Frame);

                        app.apply(Flag, $.extend({}, Selected[i]));
                    }
                });
            });

            Me.find(".tools .delete").click(function () {
                var Resource = $(this).attr("Resource");
                var Command = $(this).attr("Command");
                var PrimaryKey = $(this).attr("PrimaryKey") || app.defaultPrimaryKey;

                app.getDestElements(Resource).each(function () {
                    var Me = this;

                    var Selected = Me.GetSelected();

                    if (Selected.length == 0) {
                        app.msg("请选择您要删除的数据！");
                        return;
                    }

                    app.confirm("您确定要删除这些数据吗？", function () {
                        var Id = "";

                        for (var i = 0; i < Selected.length; i++) {
                            Id += ("," + Selected[i][PrimaryKey]);
                        }

                        Id = Id.substr(1);

                        var Data = { Command: Command };

                        Data[PrimaryKey] = Id;

                        app.server(Data, function () {
                            app.msg("删除成功！");

                            /* 刷新组件 */
                            if (Me.Data) {
                                Me.Data.Reload = true;
                            }

                            app.control($(Me));

                            if (Me.Data) {
                                delete Me.Data.Reload;
                            }
                        }, function () {
                            /* 删除失败 */
                        });
                    });
                });
            });

            Me.find(".tools .filter").submit(function () {
                var Element = $(this).find("[name]");
                var Names = Element.attr("name").split(',');
                var Value = Element.val();
                var Resource = $(this).attr("Resource");

                app.getDestElements(Resource).each(function () {
                    var Data = this.Data;

                    if (Data) {
                        $(Names).each(function () {
                            if (Value == "") {
                                delete Data[this];
                            } else {
                                Data[this] = Value;
                            }
                        });
                    }

                    app.control($(this));
                });

                return false;
            });

            Me.find(".toggle-filter").each(function () {
                var Resource = $(this).attr("Resource");

                $(this).find(".item").click(function () {
                    if ($(this).hasClass("active")) {
                        return false;
                    }

                    var Data = eval("({" + this.value + "})");

                    app.getDestElements(Resource).each(function () {
                        if (this.Data) {
                            $.extend(this.Data, Data);
                        }

                        app.control($(this));
                    });
                });
            });

            Me.find(".toggle").each(function () {
                var Items = $(this).find(".item");

                Items.click(function (e) {
                    Items.removeClass("active");

                    $(this).addClass("active");
                });
            });
        },
        tree: function (Element) {
            var Me = $(Element);
            var Root = Me.hasClass("tree") ? Me : Me.parents(".tree");
            var ParentNode = Me.hasClass("tree") ? $([]) : Me.parent("li");
            var Data = Element.Data;
            var IsTree = Root.prop("_IsTree") || false;
            var PrimaryKey = Me.attr("PrimaryKey") || app.defaultPrimaryKey;

            var CheckboxHTML = Root.hasClass("checkbox") ? "<input type=\"checkbox\"/>" : "";
            var RefreshHTML = Root.hasClass("refresh") ? "<span class=\"icon fa fa-refresh\"><span>" : "";
            var InsertHTML = Root.hasClass("insert") ? "<span class=\"icon fa fa-plus-circle\"><span>" : "";
            var UpdateHTML = Root.hasClass("update") ? "<span class=\"icon fa fa-edit\"><span>" : "";
            var DeleteHTML = Root.hasClass("delete") ? "<span class=\"icon fa fa-remove\"><span>" : "";


            if (!Data) {
                Data = Me.attr("data");

                Data = eval("({" + Data + "})");

                Element.Data = Data;
            }

            if (!Data.Command) {
                Data.Command = Me.attr("command");
            }

            if (!Data.Command) {
                throw "无法初始化树，因为没有指定读取数据的命令。";
            }

            if (!IsTree) {
                Root.each(function () {
                    this.GetSelected = function () {
                        var SelctedElement;

                        if ($(this).hasClass("checkbox")) {
                            SelctedElement = $(this).find("li>.row>input[type=checkbox]:checked").parent().parent();
                        } else {
                            SelctedElement = $(this).find("li.active");
                        }

                        var Result = [];

                        SelctedElement.each(function () {
                            Result.push($.extend({}, this.Data));
                        });

                        return Result;
                    };
                });
            }

            Me.find(">*").remove();

            Me.append("<li><div class=\"row\"><span class=\"text\">加载中...</span></div></li>");

            function AppendNode(ParentElement, Data) {
                Root.trigger("Process", [Data]);

                var Type = Data.TreeType == "node" ? "node" : "dir";

                var Node = $("<li id=\"Li" + Data[PrimaryKey]+ "\"></li>");
                var Row = $("<div class=\"row\"></div>");
                var State = $("<span class=\"state fa fa-caret-right\"></span>");
                var Checkbox = $(CheckboxHTML);
                var Icon = $("<span class=\"icon " + (Data.TreeIcon || (Type == "dir" ? "fa fa-folder" : "fa fa-file")) + "\"></span>");
                var Text = $("<span class=\"text\">" + Data.TreeText + "</span>");
                var Children = $("<ul></ul>");
                var Right = $("<div class=\"right\"></div>");
                var Refresh = $(RefreshHTML);
                var Insert = $(InsertHTML);
                var Update = $(UpdateHTML);
                var Delete = $(DeleteHTML);

                if (Data.TreeTitle) {
                    Text.attr("title", Data.TreeTitle);
                }
                
                Node.addClass(Type);
                Node.prop("Data", Data);

                Node.append(Row);

                if (Type == "dir") {
                    Node.append(Children);
                    Node.addClass("collapse");
                    Row.append(State);
                }

                Row.append(Checkbox);
                Row.append(Icon);
                Row.append(Text);
                Row.append(Right);

                Right.append(Refresh);
                Right.append(Insert);
                Right.append(Update);
                Right.append(Delete);

                ParentElement.append(Node);

                State.click(function (e) {
                    LoadChildren(Node, State, false);
                    e.stopPropagation();
                });

                if (!CheckboxHTML) {
                    Row.click(function (e) {
                        if (Root.find("li.active").length == 1 && Node.hasClass("active")) {
                            return false;
                        }

                        Root.find("li.active").removeClass("active");
                        Node.addClass("active");
                        e.stopPropagation();

                        Root.trigger("SelectedChange");
                    });
                }

                Row.dblclick(function (e) {
                    LoadChildren(Node, State, false);
                    e.stopPropagation();
                });

                Checkbox.click(function (e) {
                    e.stopPropagation();
                });

                Checkbox.change(function () {
                    Root.trigger("SelectedChange");
                });

                Checkbox.dblclick(function (e) {
                    e.stopPropagation();
                });

                Right.click(function (e) {
                    e.stopPropagation();
                });

                Right.dblclick(function (e) {
                    e.stopPropagation();
                });

                Refresh.click(function () {
                    if (Node.hasClass("expanded")) {
                        LoadChildren(Node, State, true);
                    }

                    LoadChildren(Node, State, true);
                });

                Update.click(function () {
                    Root.each(function () {
                        var OldGetSelected = this.GetSelected;

                        this.GetSelected = function () {
                            return [$.extend({}, Data)];
                        };

                        $(".update[resource=\"" + this.id + "\"]").click();

                        this.GetSelected = OldGetSelected;
                    });
                });

                Delete.click(function () {
                    Root.each(function () {
                        var OldGetSelected = this.GetSelected;

                        this.GetSelected = function () {
                            return [$.extend({}, Data)];
                        };

                        $(".delete[resource=\"" + this.id + "\"]").click();

                        this.GetSelected = OldGetSelected;
                    });
                });

                Insert.click(function () {
                    Root.each(function () {
                        var InsertButton = $(".insert[resource=\"" + this.id + "\"]");
                        var UpdateButton = $(".update[resource=\"" + this.id + "\"]");

                        var OldUpdateCommand = UpdateButton.attr("Command");
                        UpdateButton.attr("Command", InsertButton.attr("Command"));

                        Update.click();

                        UpdateButton.attr("Command", OldUpdateCommand);
                    });
                });
            }

            function LoadChildren(Node, State, Reload) {
                if (Node.hasClass("dir")) {
                    if (Node.hasClass("collapse")) {

                        var ChildrenElement = Node.find(">ul");

                        var ChildrenData = $.extend({}, Data);

                        ChildrenData[PrimaryKey] = Node.prop("Data")[PrimaryKey];

                        if (Reload) {
                            ChildrenData.Reload = true;
                        }

                        ChildrenElement.prop("Data", ChildrenData);

                        app.control(ChildrenElement, "tree");

                        State.removeClass("fa-caret-right").addClass("fa-caret-down");
                        Node.removeClass("collapse").addClass("expanded");

                    } else {
                        State.addClass("fa-caret-right").removeClass("fa-caret-down");
                        Node.removeClass("expanded").addClass("collapse");
                    }
                }
            }

            app.server(Data, function (Result) {

                Me.find(">*").remove();

                $(Result).each(function () {
                    AppendNode(Me, this);
                });


                if (ParentNode.length) {
                    var ParentState = ParentNode.find(">.row>.state");

                    if (Result.length) {
                        ParentState.css("visibility", "visible");
                    } else {
                        ParentState.css("visibility", "hidden");
                    }
                }
            });

            Root.prop("_IsTree", true);
        },
        list: function (Element) {
            var Me = $(Element);
            var Data = Element.Data;
            var IsList = Element._IsList || false;
            var Value = Me.attr("Value") || "Id";
            var Display = Me.attr("Display") || "Name";
            var NoneHTML = Me.hasClass("none") ? "<option> -- 未选择 --</option>" : "";
            var OldValue = Me.prop("_ControlValue") || Me.val();

            if (!Data) {
                Data = Me.attr("data");

                Data = eval("({" + Data + "})");

                Element.Data = Data;
            }

            if (!Data.Command) {
                Data.Command = Me.attr("command");
            }

            if (!Data.Command) {
                throw "无法初始化表格，因为没有指定读取数据的命令。";
            }

            Me.find("*").remove();

            Me.append("<option> -- 加载中... --</option>");

            app.server(Data, function (Result) {
                OldValue = Me.prop("_ControlValue") || Me.val() || OldValue;

                Me.find("*").remove();

                Me.append(NoneHTML);

                $(Result).each(function () {
                    var Item = $("<option></option>")

                    Item.val(this[Value]);
                    Item.html(this[Display]);
                    Item.prop("Data", this);

                    Me.append(Item);
                });

                if (OldValue) {
                    Me.val(OldValue);
                }
            });

            Element._IsList = true;
        }
    },
    control: function (Elements, ControlName) {
        $(Elements).each(function () {
            ControlName = ControlName || this._Control;

            this._Control = ControlName;

            app.controls[ControlName](this);
        });
    },
    events: {
        defaultRefresh: function (Button) {
            var Resource = $(Button).attr("resource");

            Resource = $("#" + Resource);

            Resource.each(function () {
                if (this._IsTable) {
                    this.Data.Reload = true;

                    app.controls.table(this);

                    delete this.Data.Reload;
                }
            });
        }
    },
    loadBody: function (Data, Callback, DisableScripts) {
        var Body = app.body;

        $.ajax({
            url: Data.Url, type: "GET", data: { Version: app.version }, success: function (HTML) {
                Body.find(">*").remove();

                var Page = document.createElement("div");

                Body.append(Page);

                Page.innerHTML = HTML;

                Page = $(Page);

                var Links = Page.find("link");

                $(Links).each(function () {
                    Body.appendChild(this);
                });

                var Scripts = Page.find("script");

                if (DisableScripts) {
                    Page.on("submit", function(e) {
                        e.stopPropagation();
                        return false;
                    });
                } else {
                    $(Scripts).each(function () {
                        if (this.src) {
                            var ScriptElement = document.createElement("script");

                            ScriptElement.src = this.src;

                            Body.appendChild(ScriptElement);
                        }

                        if (this.innerHTML) {
                            eval(this.innerHTML);
                        }
                    });
                }

                Scripts.remove();

                // Page.find("[Command]").attr("Unauthorized", "true");

                $(Data.Items).each(function () {
                    Page.find(this.Identifier).removeClass("Unauthorized");
                });

                Page.find("[Unauthorized]").remove();

                if (typeof Callback == "function") {
                    Callback();
                }
            }
        });
    }
};

var Render = {
};

$.extend(String.prototype, {
    relativeIndexOf: function (beginChar, endChar, begin, end) {
        if (typeof beginChar == "string" && typeof endChar == "string" && typeof begin == "number" && typeof end == "number") {

            var nesting = 0;

            while (begin < end) {
                if (this[begin] == endChar) {
                    if (nesting == 0) {
                        return begin;
                    }
                    else {
                        --nesting;
                    }
                }
                else if (this[begin] == beginChar) {
                    ++nesting;
                }

                ++begin;
            }

            return -1;
        } else {
            throw "String.relativeIndexOf : 参数格式错误"
        }
    }
});
$.extend(Array.prototype, {
    findIndex: function (element) {
        for (var i = 0; i < this.length; i++) {
            if (this[i] == element) {
                return i;
            }
        }
        return -1;
    }
});
$.extend(window, {
    onclick: function (e) {
        var target = e.target;
        if (target.tagName == "LABEL") {
            var target = $(target);
            var dest = target.attr("for");
            target = $(target).parent();
            while (dest && target.length) {
                var destElement = target.find("#" + dest);
                if (destElement.length) {
                    destElement.click();
                    e.stopPropagation();
                    break;
                }
                target = $(target).parent();
            }
        }
    }
});
if (!String.prototype.startsWith) {
    String.prototype.startsWith = function (text) {
        if (typeof text == "string") {
            return this.indexOf(text) == 0;
        } else {
            throw "app.useBuffered : 参数格式错误";
        }
    }
    String.prototype.endsWith = function (text) {
        if (typeof text == "string") {
            return this.indexOf(text) == this.length - text.length;
        } else {
            throw "app.useBuffered : 参数格式错误";
        }
    }
}

!function (t) {
    "use strict"; function r(t) { if (t) c[0] = c[16] = c[1] = c[2] = c[3] = c[4] = c[5] = c[6] = c[7] = c[8] = c[9] = c[10] = c[11] = c[12] = c[13] = c[14] = c[15] = 0, this.blocks = c, this.buffer8 = i; else if (n) { var r = new ArrayBuffer(68); this.buffer8 = new Uint8Array(r), this.blocks = new Uint32Array(r) } else this.blocks = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; this.h0 = this.h1 = this.h2 = this.h3 = this.start = this.bytes = 0, this.finalized = this.hashed = !1, this.first = !0 } var e = "object" == typeof process && process.versions && process.versions.node; e && (t = global); var i, h = !t.JS_MD5_TEST && "object" == typeof module && module.exports, s = "function" == typeof define && define.amd, n = !t.JS_MD5_TEST && "undefined" != typeof ArrayBuffer, f = "0123456789abcdef".split(""), a = [128, 32768, 8388608, -2147483648], o = [0, 8, 16, 24], u = ["hex", "array", "digest", "buffer", "arrayBuffer"], c = []; if (n) { var p = new ArrayBuffer(68); i = new Uint8Array(p), c = new Uint32Array(p) } var y = function (t) { return function (e) { return new r(!0).update(e)[t]() } }, d = function () { var t = y("hex"); e && (t = l(t)), t.create = function () { return new r }, t.update = function (r) { return t.create().update(r) }; for (var i = 0; i < u.length; ++i) { var h = u[i]; t[h] = y(h) } return t }, l = function (r) { var e, i; try { if (t.JS_MD5_TEST) throw "JS_MD5_TEST"; e = require("crypto"), i = require("buffer").Buffer } catch (h) { return console.log(h), r } var s = function (t) { if ("string" == typeof t) return e.createHash("md5").update(t, "utf8").digest("hex"); if (t.constructor == ArrayBuffer) t = new Uint8Array(t); else if (void 0 === t.length) return r(t); return e.createHash("md5").update(new i(t)).digest("hex") }; return s }; r.prototype.update = function (r) { if (!this.finalized) { var e = "string" != typeof r; e && r.constructor == t.ArrayBuffer && (r = new Uint8Array(r)); for (var i, h, s = 0, f = r.length || 0, a = this.blocks, u = this.buffer8; f > s;) { if (this.hashed && (this.hashed = !1, a[0] = a[16], a[16] = a[1] = a[2] = a[3] = a[4] = a[5] = a[6] = a[7] = a[8] = a[9] = a[10] = a[11] = a[12] = a[13] = a[14] = a[15] = 0), e) if (n) for (h = this.start; f > s && 64 > h; ++s) u[h++] = r[s]; else for (h = this.start; f > s && 64 > h; ++s) a[h >> 2] |= r[s] << o[3 & h++]; else if (n) for (h = this.start; f > s && 64 > h; ++s) i = r.charCodeAt(s), 128 > i ? u[h++] = i : 2048 > i ? (u[h++] = 192 | i >> 6, u[h++] = 128 | 63 & i) : 55296 > i || i >= 57344 ? (u[h++] = 224 | i >> 12, u[h++] = 128 | i >> 6 & 63, u[h++] = 128 | 63 & i) : (i = 65536 + ((1023 & i) << 10 | 1023 & r.charCodeAt(++s)), u[h++] = 240 | i >> 18, u[h++] = 128 | i >> 12 & 63, u[h++] = 128 | i >> 6 & 63, u[h++] = 128 | 63 & i); else for (h = this.start; f > s && 64 > h; ++s) i = r.charCodeAt(s), 128 > i ? a[h >> 2] |= i << o[3 & h++] : 2048 > i ? (a[h >> 2] |= (192 | i >> 6) << o[3 & h++], a[h >> 2] |= (128 | 63 & i) << o[3 & h++]) : 55296 > i || i >= 57344 ? (a[h >> 2] |= (224 | i >> 12) << o[3 & h++], a[h >> 2] |= (128 | i >> 6 & 63) << o[3 & h++], a[h >> 2] |= (128 | 63 & i) << o[3 & h++]) : (i = 65536 + ((1023 & i) << 10 | 1023 & r.charCodeAt(++s)), a[h >> 2] |= (240 | i >> 18) << o[3 & h++], a[h >> 2] |= (128 | i >> 12 & 63) << o[3 & h++], a[h >> 2] |= (128 | i >> 6 & 63) << o[3 & h++], a[h >> 2] |= (128 | 63 & i) << o[3 & h++]); this.lastByteIndex = h, this.bytes += h - this.start, h >= 64 ? (this.start = h - 64, this.hash(), this.hashed = !0) : this.start = h } return this } }, r.prototype.finalize = function () { if (!this.finalized) { this.finalized = !0; var t = this.blocks, r = this.lastByteIndex; t[r >> 2] |= a[3 & r], r >= 56 && (this.hashed || this.hash(), t[0] = t[16], t[16] = t[1] = t[2] = t[3] = t[4] = t[5] = t[6] = t[7] = t[8] = t[9] = t[10] = t[11] = t[12] = t[13] = t[14] = t[15] = 0), t[14] = this.bytes << 3, this.hash() } }, r.prototype.hash = function () { var t, r, e, i, h, s, n = this.blocks; this.first ? (t = n[0] - 680876937, t = (t << 7 | t >>> 25) - 271733879 << 0, i = (-1732584194 ^ 2004318071 & t) + n[1] - 117830708, i = (i << 12 | i >>> 20) + t << 0, e = (-271733879 ^ i & (-271733879 ^ t)) + n[2] - 1126478375, e = (e << 17 | e >>> 15) + i << 0, r = (t ^ e & (i ^ t)) + n[3] - 1316259209, r = (r << 22 | r >>> 10) + e << 0) : (t = this.h0, r = this.h1, e = this.h2, i = this.h3, t += (i ^ r & (e ^ i)) + n[0] - 680876936, t = (t << 7 | t >>> 25) + r << 0, i += (e ^ t & (r ^ e)) + n[1] - 389564586, i = (i << 12 | i >>> 20) + t << 0, e += (r ^ i & (t ^ r)) + n[2] + 606105819, e = (e << 17 | e >>> 15) + i << 0, r += (t ^ e & (i ^ t)) + n[3] - 1044525330, r = (r << 22 | r >>> 10) + e << 0), t += (i ^ r & (e ^ i)) + n[4] - 176418897, t = (t << 7 | t >>> 25) + r << 0, i += (e ^ t & (r ^ e)) + n[5] + 1200080426, i = (i << 12 | i >>> 20) + t << 0, e += (r ^ i & (t ^ r)) + n[6] - 1473231341, e = (e << 17 | e >>> 15) + i << 0, r += (t ^ e & (i ^ t)) + n[7] - 45705983, r = (r << 22 | r >>> 10) + e << 0, t += (i ^ r & (e ^ i)) + n[8] + 1770035416, t = (t << 7 | t >>> 25) + r << 0, i += (e ^ t & (r ^ e)) + n[9] - 1958414417, i = (i << 12 | i >>> 20) + t << 0, e += (r ^ i & (t ^ r)) + n[10] - 42063, e = (e << 17 | e >>> 15) + i << 0, r += (t ^ e & (i ^ t)) + n[11] - 1990404162, r = (r << 22 | r >>> 10) + e << 0, t += (i ^ r & (e ^ i)) + n[12] + 1804603682, t = (t << 7 | t >>> 25) + r << 0, i += (e ^ t & (r ^ e)) + n[13] - 40341101, i = (i << 12 | i >>> 20) + t << 0, e += (r ^ i & (t ^ r)) + n[14] - 1502002290, e = (e << 17 | e >>> 15) + i << 0, r += (t ^ e & (i ^ t)) + n[15] + 1236535329, r = (r << 22 | r >>> 10) + e << 0, t += (e ^ i & (r ^ e)) + n[1] - 165796510, t = (t << 5 | t >>> 27) + r << 0, i += (r ^ e & (t ^ r)) + n[6] - 1069501632, i = (i << 9 | i >>> 23) + t << 0, e += (t ^ r & (i ^ t)) + n[11] + 643717713, e = (e << 14 | e >>> 18) + i << 0, r += (i ^ t & (e ^ i)) + n[0] - 373897302, r = (r << 20 | r >>> 12) + e << 0, t += (e ^ i & (r ^ e)) + n[5] - 701558691, t = (t << 5 | t >>> 27) + r << 0, i += (r ^ e & (t ^ r)) + n[10] + 38016083, i = (i << 9 | i >>> 23) + t << 0, e += (t ^ r & (i ^ t)) + n[15] - 660478335, e = (e << 14 | e >>> 18) + i << 0, r += (i ^ t & (e ^ i)) + n[4] - 405537848, r = (r << 20 | r >>> 12) + e << 0, t += (e ^ i & (r ^ e)) + n[9] + 568446438, t = (t << 5 | t >>> 27) + r << 0, i += (r ^ e & (t ^ r)) + n[14] - 1019803690, i = (i << 9 | i >>> 23) + t << 0, e += (t ^ r & (i ^ t)) + n[3] - 187363961, e = (e << 14 | e >>> 18) + i << 0, r += (i ^ t & (e ^ i)) + n[8] + 1163531501, r = (r << 20 | r >>> 12) + e << 0, t += (e ^ i & (r ^ e)) + n[13] - 1444681467, t = (t << 5 | t >>> 27) + r << 0, i += (r ^ e & (t ^ r)) + n[2] - 51403784, i = (i << 9 | i >>> 23) + t << 0, e += (t ^ r & (i ^ t)) + n[7] + 1735328473, e = (e << 14 | e >>> 18) + i << 0, r += (i ^ t & (e ^ i)) + n[12] - 1926607734, r = (r << 20 | r >>> 12) + e << 0, h = r ^ e, t += (h ^ i) + n[5] - 378558, t = (t << 4 | t >>> 28) + r << 0, i += (h ^ t) + n[8] - 2022574463, i = (i << 11 | i >>> 21) + t << 0, s = i ^ t, e += (s ^ r) + n[11] + 1839030562, e = (e << 16 | e >>> 16) + i << 0, r += (s ^ e) + n[14] - 35309556, r = (r << 23 | r >>> 9) + e << 0, h = r ^ e, t += (h ^ i) + n[1] - 1530992060, t = (t << 4 | t >>> 28) + r << 0, i += (h ^ t) + n[4] + 1272893353, i = (i << 11 | i >>> 21) + t << 0, s = i ^ t, e += (s ^ r) + n[7] - 155497632, e = (e << 16 | e >>> 16) + i << 0, r += (s ^ e) + n[10] - 1094730640, r = (r << 23 | r >>> 9) + e << 0, h = r ^ e, t += (h ^ i) + n[13] + 681279174, t = (t << 4 | t >>> 28) + r << 0, i += (h ^ t) + n[0] - 358537222, i = (i << 11 | i >>> 21) + t << 0, s = i ^ t, e += (s ^ r) + n[3] - 722521979, e = (e << 16 | e >>> 16) + i << 0, r += (s ^ e) + n[6] + 76029189, r = (r << 23 | r >>> 9) + e << 0, h = r ^ e, t += (h ^ i) + n[9] - 640364487, t = (t << 4 | t >>> 28) + r << 0, i += (h ^ t) + n[12] - 421815835, i = (i << 11 | i >>> 21) + t << 0, s = i ^ t, e += (s ^ r) + n[15] + 530742520, e = (e << 16 | e >>> 16) + i << 0, r += (s ^ e) + n[2] - 995338651, r = (r << 23 | r >>> 9) + e << 0, t += (e ^ (r | ~i)) + n[0] - 198630844, t = (t << 6 | t >>> 26) + r << 0, i += (r ^ (t | ~e)) + n[7] + 1126891415, i = (i << 10 | i >>> 22) + t << 0, e += (t ^ (i | ~r)) + n[14] - 1416354905, e = (e << 15 | e >>> 17) + i << 0, r += (i ^ (e | ~t)) + n[5] - 57434055, r = (r << 21 | r >>> 11) + e << 0, t += (e ^ (r | ~i)) + n[12] + 1700485571, t = (t << 6 | t >>> 26) + r << 0, i += (r ^ (t | ~e)) + n[3] - 1894986606, i = (i << 10 | i >>> 22) + t << 0, e += (t ^ (i | ~r)) + n[10] - 1051523, e = (e << 15 | e >>> 17) + i << 0, r += (i ^ (e | ~t)) + n[1] - 2054922799, r = (r << 21 | r >>> 11) + e << 0, t += (e ^ (r | ~i)) + n[8] + 1873313359, t = (t << 6 | t >>> 26) + r << 0, i += (r ^ (t | ~e)) + n[15] - 30611744, i = (i << 10 | i >>> 22) + t << 0, e += (t ^ (i | ~r)) + n[6] - 1560198380, e = (e << 15 | e >>> 17) + i << 0, r += (i ^ (e | ~t)) + n[13] + 1309151649, r = (r << 21 | r >>> 11) + e << 0, t += (e ^ (r | ~i)) + n[4] - 145523070, t = (t << 6 | t >>> 26) + r << 0, i += (r ^ (t | ~e)) + n[11] - 1120210379, i = (i << 10 | i >>> 22) + t << 0, e += (t ^ (i | ~r)) + n[2] + 718787259, e = (e << 15 | e >>> 17) + i << 0, r += (i ^ (e | ~t)) + n[9] - 343485551, r = (r << 21 | r >>> 11) + e << 0, this.first ? (this.h0 = t + 1732584193 << 0, this.h1 = r - 271733879 << 0, this.h2 = e - 1732584194 << 0, this.h3 = i + 271733878 << 0, this.first = !1) : (this.h0 = this.h0 + t << 0, this.h1 = this.h1 + r << 0, this.h2 = this.h2 + e << 0, this.h3 = this.h3 + i << 0) }, r.prototype.hex = function () { this.finalize(); var t = this.h0, r = this.h1, e = this.h2, i = this.h3; return f[t >> 4 & 15] + f[15 & t] + f[t >> 12 & 15] + f[t >> 8 & 15] + f[t >> 20 & 15] + f[t >> 16 & 15] + f[t >> 28 & 15] + f[t >> 24 & 15] + f[r >> 4 & 15] + f[15 & r] + f[r >> 12 & 15] + f[r >> 8 & 15] + f[r >> 20 & 15] + f[r >> 16 & 15] + f[r >> 28 & 15] + f[r >> 24 & 15] + f[e >> 4 & 15] + f[15 & e] + f[e >> 12 & 15] + f[e >> 8 & 15] + f[e >> 20 & 15] + f[e >> 16 & 15] + f[e >> 28 & 15] + f[e >> 24 & 15] + f[i >> 4 & 15] + f[15 & i] + f[i >> 12 & 15] + f[i >> 8 & 15] + f[i >> 20 & 15] + f[i >> 16 & 15] + f[i >> 28 & 15] + f[i >> 24 & 15] }, r.prototype.toString = r.prototype.hex, r.prototype.digest = function () { this.finalize(); var t = this.h0, r = this.h1, e = this.h2, i = this.h3; return [255 & t, t >> 8 & 255, t >> 16 & 255, t >> 24 & 255, 255 & r, r >> 8 & 255, r >> 16 & 255, r >> 24 & 255, 255 & e, e >> 8 & 255, e >> 16 & 255, e >> 24 & 255, 255 & i, i >> 8 & 255, i >> 16 & 255, i >> 24 & 255] }, r.prototype.array = r.prototype.digest, r.prototype.arrayBuffer = function () { this.finalize(); var t = new ArrayBuffer(16), r = new Uint32Array(t); return r[0] = this.h0, r[1] = this.h1, r[2] = this.h2, r[3] = this.h3, t }, r.prototype.buffer = r.prototype.arrayBuffer; var v = d(); h ? module.exports = v : (t.md5 = v, s && define(function () { return v }))
}(this);

function Logged() {
    app.server({ Command: "ReadAllAuthorizedMenus" }, function (Return) {
        var MenusMap = { "0": {}};

        $(Return).each(function () {
            MenusMap[this.Id] = this;

            if (MenusMap[this.ParentId].Items) {
                MenusMap[this.ParentId].Items.push(this);
            } else {
                MenusMap[this.ParentId].Items = [this];
            }
        });

        var RootMenus = MenusMap[app.appid].Items;

        var MenusElement = $("#Main #Top #Menu");
        var PagesElement = $("#Main #Left #Page");

        $(RootMenus).each(function () {
            MenusElement.append(app.format("<div id=\"Menu_@Id\" class=\"item\"><button class=\"text\">@Name</button></div>", this));

            MenusElement.find("#Menu_" + this.Id).prop("Data", this);
        });

        MenusElement.find(".item").click(function () {
            if ($(this).hasClass("active")) {
                return false;
            }

            MenusElement.find(".active").removeClass("active");

            $(this).addClass("active");

            PagesElement.find(".item").remove();

            $(this.Data.Items).each(function () {
                PagesElement.append(app.format("<div id=\"Page_@Id\" class=\"item\"><span class=\"state\"></span> <span class=\"text\">@Name</span></div>", this));

                PagesElement.find("#Page_" + this.Id).prop("Data", this);
            });

            PagesElement.find(".item").click(function () {
                PagesElement.find(".active").removeClass("active");

                $(this).addClass("active");

                app.body.find(">*").remove();

                app.body.append("<h1 style=\"text-align:center;color:#333;position:absolute;width:100%;margin:0;top:40%;\">页面正在加载...</h1>");

                if (this.Data.Type != 3) {
                    app.confirm("无效的菜单，因为 -- " + this.Data.Name + " -- 不是一个页面。");
                    return false;
                }

                app.loadBody(this.Data);
            });
        });

        MenusElement.find(".item:first").click();

    });
}

Logged();